# -*- coding: utf-8 -*-
"""
    utils.minister_utils
    ~~~~~~~~~~~~~~~~~~~~

    大臣相关, 纯公式计算

    :create by: lyncir
    :date: 2018-08-15 16:05:42 (+0800)
    :last modified date: 2019-03-21 11:22:22 (+0800)
    :last modified by: lyncir
"""
import math
import itertools

from app.area.component.buff_component import CalculateManager


def sum_attr_by_buff(base_attr, buff_addition):
    """
    根据buff数据计算加成后的数值

    :param list base_attr: 基础属性
    :param list buff_addition: buff列表
    """
    return [CalculateManager.get_new_value(base_attr[0],
                                           a_v=buff_addition[0][0],
                                           a_p=buff_addition[0][1],
                                           form=3) - base_attr[0],
            CalculateManager.get_new_value(base_attr[1],
                                           a_v=buff_addition[1][0],
                                           a_p=buff_addition[1][1],
                                           form=3) - base_attr[1],
            CalculateManager.get_new_value(base_attr[2],
                                           a_v=buff_addition[2][0],
                                           a_p=buff_addition[2][1],
                                           form=3) - base_attr[2],
            CalculateManager.get_new_value(base_attr[3],
                                           a_v=buff_addition[3][0],
                                           a_p=buff_addition[3][1],
                                           form=3) - base_attr[3]]


def get_minister_base_attr(lv, aptitude, rank_ratio, star_ratio, guard_ratio, equipment_ratio):
    """
    获取大臣的基础属性

    单项基础属性 = (星级系数 + 守护系数 + 装备系数) *((等级+2) * (等级-1) * 资质 * 0.1 * 爵位系数 + 资质 * 12 + 10))

    :param int lv: 大臣等级
    :param list aptitude: 大臣资质，列表，商农政军四类
    :param float rank_ratio: 爵位系数
    :param list star_ratio: 星级系数，列表，商农政军四类
    :param list guard_ratio: 守护系数 列表 商农政军四类
    :param list equipment_ratio: 装备系数 列表 商农政军四类
    :return: 基础属性列表
    :rtype: list
    """
    base_attr = [0, 0, 0, 0]

    for index in range(len(base_attr)):
        single_aptitude = sum(aptitude[index].itervalues())
        single_star_ratio = star_ratio[index]
        single_guard_ratio = guard_ratio[index]
        single_equipment_ratio = equipment_ratio[index]

        attr_num = int(math.ceil((single_star_ratio + single_guard_ratio + single_equipment_ratio) * ((lv + 2) * (lv - 1) *
                                 single_aptitude * 0.1 * rank_ratio + single_aptitude * 12 + 10)))

        base_attr[index] = attr_num

    return base_attr


def get_minister_rank_attr(attribute_list):
    """
    获取大臣爵位加成属性

    :param list attribute_list: 属性列表
    :return: 爵位加成属性列表 可能为[]
    :rtype: list
    """
    if not attribute_list:
        return [0, 0, 0, 0]

    return map(sum, itertools.izip_longest(*attribute_list, fillvalue=0))


def get_minister_grade_attr(grade_buff_list):
    """
    获取大臣官品加成属性

    GradeBuffList 组成: [初始攻击力加成, 技能触发概率加成, 名臣总属性加成]

    :param list grade_buff_list: 对应官品等级的buff列表
    :return: 官品加成属性列表
    :rtype: list
    """
    if not grade_buff_list:
        return [0, 0, 0, 0]

    return grade_buff_list[-1]


def get_minister_treasure_attr(treasure):
    """
    获取大臣珍宝加成属性

    :param list treasure: 大臣拥有的珍宝属性
    :return: 珍宝加成属性列表
    :rtype: list
    """
    if not treasure:
        return [0, 0, 0, 0]

    return treasure


def get_minister_destiny_lv_attr(destiny_attr):
    """
    获取大臣命格命格等级加成属性
    :param destiny_attr: 命格等级加成属性
    :rtype: list
    """
    if not destiny_attr:
        destiny_attr = [0, 0, 0, 0]

    return destiny_attr


def get_minister_destiny_wake_lv_attr(destiny_wake_attr):
    """
    获取大臣命格命格觉醒等级加成属性
    :param destiny_wake_attr: 命格觉醒等级加成属性
    :rtype: list
    """
    if not destiny_wake_attr:
        destiny_wake_attr = [0, 0, 0, 0]

    return destiny_wake_attr


def retrieve_minister_buff_addition(buff_dict, indicator_buff_list,
                                    power_buff_list, group_buff_list,
                                    house_buff_list, destiny_buff_list, destiny_wake_buff_list,
                                    break_through_buff_list, equipment_buff_list):
    """
    获取作用在某个大臣身上的所有buff加成数据

    :param break_through_buff_list: 突破Buff列表
    :param dict buff_dict: 所有角色buff数据 {buff_type: [add_value, add_percent]}
    :param list indicator_buff_list: 大臣系统对国力影响buff类型列表
    :param list power_buff_list: 势力buff列表
    :param list group_buff_list: 大臣组buff列表(清帝，女将)
    :param list house_buff_list: 名臣府邸buff列表
    :param list destiny_buff_list: 命格buff列表
    :param list destiny_wake_buff_list: 命格觉醒buff列表
    :param list equipment_buff_list: 装备加成buff列表
    :return: [[+商,+商%],[+农,+农%],[+政,+政%],[+军,+军%]]
    :rtype: list
    """
    # 全局大臣buff
    b_list = map(list, zip(indicator_buff_list))

    # 清帝buff + 势力buff
    if power_buff_list and group_buff_list:
        b_list = map(list, zip(indicator_buff_list, group_buff_list, power_buff_list))

    # 势力buff
    elif power_buff_list and (not group_buff_list):
        b_list = map(list, zip(indicator_buff_list, power_buff_list))

    # 清帝buff
    elif (not power_buff_list) and group_buff_list:
        b_list = map(list, zip(indicator_buff_list, group_buff_list))

    # 名臣府邸buff
    if house_buff_list:
        map(lambda x: x[0].append(x[1]), zip(b_list, house_buff_list))
    # 命格buff
    if destiny_buff_list:
        map(lambda x: x[0].append(x[1]), zip(b_list, destiny_buff_list))
    # 命格觉醒buff
    if destiny_wake_buff_list:
        map(lambda x: x[0].append(x[1]), zip(b_list, destiny_wake_buff_list))
    # 突破buff
    if break_through_buff_list:
        map(lambda x: x[0].append(x[1]), zip(b_list, break_through_buff_list))
    # 装备buff
    if equipment_buff_list:
        map(lambda x: x[0].append(x[1]), zip(b_list, equipment_buff_list))

    # 获取buff加成属性
    # len(buff_addition)=4, [[+商,+商%],[+农,+农%],[+政,+政%],[+军,+军%]]
    buff_addition = []
    for buff_type_list in b_list:
        buff_type_list = set(buff_type_list)  # 去除重复的buff类型
        addition_list = map(lambda x: buff_dict.get(x, [0, 0]), buff_type_list)
        r = [0, 0]
        for add in addition_list:
            r[0] += add[0]
            r[1] += add[1]
        buff_addition.append(r)

    return buff_addition


def get_minister_buff_attr(base_attr, buff_addition):
    """
    获取大臣buff加成属性
    buff_addition: [[+商,+商%],[+农,+农%],[+政,+政%],[+军,+军%]]

    :param list base_attr: 基础属性
    :param list buff_addition: buff列表
    :return: buff加成属性列表
    :rtype: list
    """
    return sum_attr_by_buff(base_attr, buff_addition)


def get_minister_attr(base_attr, rank_attr, grade_attr, treasure_attr, buff_attr, destiny_attr, destiny_wake_attr,
                      equipment_attr):
    """
    获取大臣总属性 = 基础属性
                   + 封爵加成属性
                   + 官品加成属性
                   + 珍宝加成属性
                   + buff加成属性
                   + 命格等级加成属性
                   + 命格觉醒等级加成属性
                   + 装备加成属性

    :param list base_attr: 基础属性
    :param list rank_attr: 封爵加成属性
    :param list grade_attr: 官品加成属性
    :param list treasure_attr: 珍宝加成属性
    :param list buff_attr: buff加成属性
    :param list destiny_attr: 命格等级加成属性
    :param list destiny_wake_attr: 命格觉醒等级加成属性
    :param list equipment_attr: 装备加成属性
    """
    if not rank_attr:
        rank_attr = [0, 0, 0, 0]

    attr_list = [{"Base": base_attr[i],
                  "Alliance": 0,
                  "Treasure": treasure_attr[i],
                  "Halo": 0,
                  "Rank": rank_attr[i],
                  "Grade": grade_attr[i],
                  "Buff": buff_attr[i],
                  "Destiny": destiny_attr[i],
                  "DestinyWake": destiny_wake_attr[i],
                  "Equipment": equipment_attr[i],
                  } for i in range(0, 4)]
    return attr_list


def sum_minister_attr(attr_list):
    """
    把大臣属性字典列表转换为列表

    :param list attr_list: 大臣属性字典列表。eg. [{商}, {农}, {政}, {军}]
    :return: [商,农,政,军]
    :rtype: list
    """
    return map(lambda attr_dict: sum(attr_dict.itervalues()), attr_list)


def get_fight_power(aptitude, attribute, lv):
    """
    获得大臣战力

    公式: (大臣总资质 * 等级) ** 0.9 + 0.1 * 大臣总属性 ** 0.9

    :param int aptitude: 大臣总资质
    :param int attribute: 大臣总属性
    :param int lv: 大臣等级
    :return: 战力
    :rtype: int
    """
    return int((aptitude * lv) ** 0.9 + 0.1 * attribute ** 0.9)


def get_minister_skill_effect(minister_skill, skill_rank, skill_cfg_tree,
                              grade_buff_list):
    """
    获取大臣技能效果: 四属性暴击率和暴击伤害

    GradeBuffList 组成: [初始攻击力加成, 技能触发概率加成, 名臣总属性加成]
    skill_cfg_tree 格式: {"Type": {"Rank": {"BaseRate": 35,
                                            "BaseDamage": 150,
                                            "AddDamage": 1}}}

    :param list minister_skill: 大臣四属性技能等级
    :param list skill_rank: 大臣技能星级列表
    :param dict skill_cfg_tree: 大臣校场技能配置
    :param list grade_buff_list: 官品buff列表
    :return: 四属性暴击率和暴击伤害
    :rtype: tuple(list, list)
    """
    # 四属性暴击率
    crt_ratio = [0, 0, 0, 0]
    # 四属性暴击伤害
    crt_damage = [0, 0, 0, 0]

    for index in range(4):
        rank_type = index + 1
        rank = skill_rank[index]

        if str(rank_type) not in skill_cfg_tree:
            continue

        if str(rank) not in skill_cfg_tree[str(rank_type)]:
            continue

        skill_cfg = skill_cfg_tree[str(rank_type)][str(rank)]

        # 如果有官品加成，则增加技能基础触发率
        if grade_buff_list:
            crt_ratio[index] = skill_cfg['BaseRate'] + grade_buff_list[1][index]

        # 没有则为原来的触发率
        else:
            crt_ratio[index] = skill_cfg['BaseRate']

        crt_damage[index] = skill_cfg['BaseDamage'] + skill_cfg['AddDamage'] * (minister_skill[index] - 1)

    return crt_ratio, crt_damage
